package com.sangcomz.fishbun.datasource;

import com.sangcomz.fishbun.MimeType;
import com.sangcomz.fishbun.ui.album.model.Album;
import com.sangcomz.fishbun.ui.album.model.AlbumMetaData;
import com.sangcomz.fishbun.util.future.CallableFutureTask;

import java.util.*;
import java.util.concurrent.Callable;

import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.data.dataability.DataAbilityPredicates;
import ohos.data.resultset.ResultSet;
import ohos.utils.net.Uri;

import static ohos.media.photokit.metadata.AVStorage.AVBaseColumns.*;
import static ohos.media.photokit.metadata.AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI;

public class ImageDataSourceImpl implements ImageDataSource {

    private DataAbilityHelper dataAbilityHelper;

    public ImageDataSourceImpl(DataAbilityHelper dataAbilityHelper) throws DataAbilityRemoteException {
        this.dataAbilityHelper = dataAbilityHelper;
    }

    private ArrayList<Uri> addedPathList = new ArrayList<>();

    @Override
    public CallableFutureTask<List<Album>> getAlbumList(String allViewTitle, List<MimeType> exceptMimeTypeList, List<String> specifyFolderList) {
        CallableFutureTask<List<Album>> callableFutureTask = new CallableFutureTask<>(new Callable<List<Album>>() {
            @Override
            public List<Album> call() throws Exception {
                LinkedHashMap<Long, AlbumData> albumDataMap = new LinkedHashMap<>();
                String orderBy = "_id";
                String[] projection = new String[]{ID, DISPLAY_NAME, MIME_TYPE};

                DataAbilityPredicates predicates = new DataAbilityPredicates();
                predicates.orderByDesc(orderBy);

                ResultSet c = dataAbilityHelper.query(EXTERNAL_DATA_ABILITY_URI, projection, null);

                int totalCount = 0;
                Uri allViewThumbnailPath = Uri.EMPTY_URI;

                if (c != null) {
                    while (c.goToNextRow()) {
                        Long bucketId = Long.valueOf(String.valueOf(c.getInt(c.getColumnIndexForName(ID))));
                        String bucketDisplayName = c.getString(c.getColumnIndexForName(DISPLAY_NAME));
                        String bucketMimeType = c.getString(c.getColumnIndexForName(MIME_TYPE));
                        int imgId = c.getInt(c.getColumnIndexForName(ID));

                        if (isExceptImage(
                                bucketMimeType,
                                bucketDisplayName,
                                exceptMimeTypeList,
                                specifyFolderList)
                        ) {
                            continue;
                        }

                        AlbumData albumData = albumDataMap.get(bucketId);

                        if (albumData == null) {
                            Uri imagePath = Uri.appendEncodedPathToUri(EXTERNAL_DATA_ABILITY_URI, "" + imgId);

                            albumDataMap.put(bucketId, new AlbumData(bucketDisplayName, imagePath, 1));

                            if (allViewThumbnailPath == Uri.EMPTY_URI) allViewThumbnailPath = imagePath;

                        } else {
                            albumData.imageCount++;
                        }

                        totalCount++;

                    }
                    c.close();
                }

                if (totalCount == 0) albumDataMap.clear();

                List<Album> albumList = new ArrayList<>();

                if (!isNotContainsSpecifyFolderList(specifyFolderList, allViewTitle)
                        && !albumDataMap.isEmpty()
                ) {
                    albumList.add(0, new Album(0L, allViewTitle, new AlbumMetaData(totalCount, allViewThumbnailPath.toString())));
                }

//                for (Map.Entry<Long, AlbumData> entry : albumDataMap.entrySet()) {
//                    AlbumData value = entry.getValue();
//                    albumList.add(new Album(entry.getKey(), value.displayName, new AlbumMetaData(value.imageCount, value.thumbnailPath.toString())));
//                }

                return albumList;
            }
        });

        return callableFutureTask;
    }

    @Override
    public CallableFutureTask<List<Uri>> getAllBucketImageUri(Long bucketId, List<MimeType> exceptMimeTypeList, List<String> specifyFolderList) {
        CallableFutureTask<List<Uri>> callableFutureTask = new CallableFutureTask<>(new Callable<List<Uri>>() {
            @Override
            public List<Uri> call() throws Exception {
                List<Uri> imageUris = new ArrayList<>();
                String selection = "$BUCKET_ID";
                String mBucketId = String.valueOf(bucketId);
                String sort = "$_ID";

                Uri images = EXTERNAL_DATA_ABILITY_URI;

                ResultSet c = null;
                if (!mBucketId.equals("0")) {
                    DataAbilityPredicates predicates = new DataAbilityPredicates();
                    //TODO 暂时去掉排序
//                    predicates.orderByDesc(sort);
                    predicates.equalTo(selection, mBucketId);
                    c = dataAbilityHelper.query(images, null, predicates);
                } else {
                    DataAbilityPredicates predicates = new DataAbilityPredicates();
                    predicates.orderByDesc(sort);
                    //TODO 暂时去掉排序
//                    c = dataAbilityHelper.query(images, null, predicates);
                    c = dataAbilityHelper.query(images, null, null);
                }

                try {
                    if (c.goToFirstRow()) {
                        do {
                            String mimeType = c.getString(c.getColumnIndexForName(MIME_TYPE));
                            String folderName = c.getString(c.getColumnIndexForName(DISPLAY_NAME));
                            if (isExceptMemeType(exceptMimeTypeList, mimeType)
                                    || isNotContainsSpecifyFolderList(specifyFolderList, folderName)
                            ) {
                                continue;
                            }
                            int imgId = c.getInt(c.getColumnIndexForName(ID));
                            Uri path = Uri.appendEncodedPathToUri(EXTERNAL_DATA_ABILITY_URI, "" + imgId);
                            imageUris.add(path);
                        } while (c.goToNextRow());
                    }
                } finally {
                    if (!c.isClosed()) c.close();
                }

                return imageUris;
            }
        });

        return callableFutureTask;
    }

    @Override
    public CallableFutureTask<AlbumMetaData> getAlbumMetaData(Long bucketId, List<MimeType> exceptMimeTypeList, List<String> specifyFolderList) {
        CallableFutureTask<AlbumMetaData> callableFutureTask = new CallableFutureTask<>(new Callable<AlbumMetaData>() {
            @Override
            public AlbumMetaData call() throws Exception {
                String selection = "$BUCKET_ID";
                String sort = "$_ID";
                String mBucketId = String.valueOf(bucketId);

                Uri images = EXTERNAL_DATA_ABILITY_URI;
                ResultSet c = null;
                if (!mBucketId.equals("0")) {
                    DataAbilityPredicates predicates = new DataAbilityPredicates();
                    predicates.orderByDesc(sort);
                    predicates.equalTo(selection, mBucketId);
                    c = dataAbilityHelper.query(images, null, predicates);
                } else {
                    DataAbilityPredicates predicates = new DataAbilityPredicates();
                    predicates.orderByDesc(sort);
                    c = dataAbilityHelper.query(images, null, predicates);
                }

                int count = 0;
                Uri thumbnailPath = Uri.EMPTY_URI;

                try {
                    if (c.goToFirstRow()) {
                        do {
                            String mimeType = c.getString(c.getColumnIndexForName(MIME_TYPE));
                            String folderName = c.getString(c.getColumnIndexForName(DISPLAY_NAME));

                            if (isExceptMemeType(exceptMimeTypeList, mimeType)
                                    || isNotContainsSpecifyFolderList(specifyFolderList, folderName)
                            ) {
                                continue;
                            }
                            int imgId = c.getInt(c.getColumnIndexForName(ID));
                            if (thumbnailPath == Uri.EMPTY_URI) {
                                thumbnailPath = Uri.appendEncodedPathToUri(EXTERNAL_DATA_ABILITY_URI, "" + imgId);
                            }
                            count++;
                        } while (c.goToNextRow());
                    }
                } finally {
                    if (!c.isClosed()) c.close();
                }

                return new AlbumMetaData(count, thumbnailPath.toString());
            }
        });

        return callableFutureTask;
    }

    @Override
    public CallableFutureTask<String> getDirectoryPath(Long bucketId) {
        CallableFutureTask<String> callableFutureTask = new CallableFutureTask<>(new Callable<String>() {
            @Override
            public String call() throws Exception {
                String path = "";
                String selection = "$BUCKET_ID";
                String mBucketId = String.valueOf(bucketId);

                Uri images = EXTERNAL_DATA_ABILITY_URI;
                ResultSet c = null;
                if (!mBucketId.equals("0")) {
                    DataAbilityPredicates predicates = new DataAbilityPredicates();
                    predicates.equalTo(selection, mBucketId);
                    c = dataAbilityHelper.query(images, null, predicates);
                } else {
                    c = dataAbilityHelper.query(images, null, null);
                }

                try {
                    if (c.goToFirstRow()) {
                        path = getPathDir(
                                c.getString(c.getColumnIndexForName(DATA)),
                                c.getString(c.getColumnIndexForName(DISPLAY_NAME))
                        );
                    }
                } finally {
                    if (!c.isClosed()) c.close();
                }

                return path;
            }
        });
        return callableFutureTask;
    }

    @Override
    public void addAddedPath(Uri addedImage) {
        addedPathList.add(addedImage);
    }

    @Override
    public void addAllAddedPath(List<Uri> addedImageList) {
        addedPathList.addAll(addedImageList);
    }

    @Override
    public List<Uri> getAddedPathList() {
        return addedPathList;
    }

    private String getPathDir(String path, String fileName) {
        return path.replace("/$fileName", "");
    }

    private boolean isExceptMemeType(
            List<MimeType> mimeTypes,
            String mimeType
    ) {
        for (int i = 0; i < mimeTypes.size(); i++) {
            MimeType type = mimeTypes.get(i);
//            if (type.equalsMimeType(mimeType)) return true;
            if (type.name().equals(mimeType)) {
                return true;
            }
        }
        return false;
    }

    private boolean isNotContainsSpecifyFolderList(
            List<String> specifyFolderList,
            String displayBundleName
    ) {
        if (specifyFolderList.isEmpty()) return false;
        else return !specifyFolderList.contains(displayBundleName);
    }

    private boolean isExceptImage(
            String bucketMimeType,
            String bucketDisplayName,
            List<MimeType> exceptMimeTypeList,
            List<String> specifyFolderList
    ) {
        return isExceptMemeType(exceptMimeTypeList, bucketMimeType)
                || isNotContainsSpecifyFolderList(specifyFolderList, bucketDisplayName);
    }

    private class AlbumData {
        String displayName;
        Uri thumbnailPath;
        int imageCount;

        public AlbumData(String displayName, Uri thumbnailPath, int imageCount) {
            this.displayName = displayName;
            this.thumbnailPath = thumbnailPath;
            this.imageCount = imageCount;
        }

        public String getDisplayName() {
            return displayName;
        }

        public void setDisplayName(String displayName) {
            this.displayName = displayName;
        }

        public Uri getThumbnailPath() {
            return thumbnailPath;
        }

        public void setThumbnailPath(Uri thumbnailPath) {
            this.thumbnailPath = thumbnailPath;
        }

        public int getImageCount() {
            return imageCount;
        }

        public void setImageCount(int imageCount) {
            this.imageCount = imageCount;
        }
    }
}